import requests
import pandas as pd
from datetime import datetime, timedelta
from bs4 import BeautifulSoup
import json
import time
import logging

class SinaForexFetcher:
    """
    新浪财经汇率数据获取器
    """
    
    def __init__(self):
        self.base_url = "http://biz.finance.sina.com.cn/forex/forex.php"
        self.session = requests.Session()
        self.session.encoding = 'gb2312'
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'Accept-Encoding': 'gzip, deflate',
            'Connection': 'keep-alive',
            'Upgrade-Insecure-Requests': '1'
        })
        self.logger = logging.getLogger(__name__)
    
    def get_historical_rates(self, currency_pair, start_date, end_date):
        """
        获取历史汇率数据
        
        Args:
            currency_pair: 货币对代码，如 'USDCNY'
            start_date: 开始日期 (datetime)
            end_date: 结束日期 (datetime)
            
        Returns:
            pandas.DataFrame: 汇率数据
        """
        try:
            # 格式化日期
            start_str = start_date.strftime('%Y-%m-%d')
            end_str = end_date.strftime('%Y-%m-%d')
            
            # 构建请求URL
            params = {
                'mod': 'history',
                'startdate': start_str,
                'enddate': end_str,
                'symbol': currency_pair,
                'type': '0'
            }
            
            self.logger.info(f"正在获取 {currency_pair} 从 {start_str} 到 {end_str} 的数据")
            
            # 发送请求
            response = self.session.get(self.base_url, params=params, timeout=30)
            response.raise_for_status()
            
            # 解析HTML数据
            forex_data = self._parse_html_response(response.text)
            
            if forex_data:
                # 转换为DataFrame
                df = pd.DataFrame(forex_data)
                df['symbol'] = currency_pair
                
                # 数据类型转换
                df = self._convert_data_types(df)
                
                # 按日期排序
                df = df.sort_values('date').reset_index(drop=True)
                
                self.logger.info(f"成功获取 {currency_pair} 数据，共 {len(df)} 条记录")
                return df
            else:
                self.logger.warning(f"未能获取到 {currency_pair} 的数据")
                return pd.DataFrame()
                
        except requests.RequestException as e:
            self.logger.error(f"网络请求失败: {str(e)}")
            return pd.DataFrame()
        except Exception as e:
            self.logger.error(f"获取汇率数据时发生错误: {str(e)}")
            return pd.DataFrame()
    
    def _parse_html_response(self, html_content):
        """
        解析HTML响应内容
        """
        try:
            soup = BeautifulSoup(html_content, 'lxml')
            
            # 查找数据表格
            table = soup.find('table', {'class': 'list_table'})
            if not table:
                # 尝试其他可能的表格标识
                table = soup.find('table', {'class': 'forex_table'})
            if not table:
                table = soup.find('table')
            
            if not table:
                self.logger.warning("未找到数据表格")
                return []
            
            # 解析表格数据
            rows = table.find_all('tr')
            data = []
            
            for row in rows[1:]:  # 跳过表头
                cols = row.find_all('td')
                if len(cols) >= 5:  # 确保有足够的列
                    try:
                        record = {
                            'date': cols[0].get_text(strip=True),
                            'open': cols[1].get_text(strip=True),
                            'high': cols[2].get_text(strip=True),
                            'low': cols[3].get_text(strip=True),
                            'close': cols[4].get_text(strip=True),
                            'volume': cols[5].get_text(strip=True) if len(cols) > 5 else '0'
                        }
                        data.append(record)
                    except Exception as e:
                        self.logger.warning(f"解析行数据时出错: {str(e)}")
                        continue
            
            return data
            
        except Exception as e:
            self.logger.error(f"解析HTML内容时出错: {str(e)}")
            return []
    
    def _convert_data_types(self, df):
        """
        转换数据类型
        """
        try:
            # 转换日期
            df['date'] = pd.to_datetime(df['date'])
            
            # 转换数值列
            numeric_columns = ['open', 'high', 'low', 'close', 'volume']
            for col in numeric_columns:
                if col in df.columns:
                    df[col] = pd.to_numeric(df[col], errors='coerce')
            
            # 处理缺失值
            df = df.dropna(subset=['date', 'close'])
            
            return df
            
        except Exception as e:
            self.logger.error(f"数据类型转换时出错: {str(e)}")
            return df
    
    def get_real_time_rate(self, currency_pair):
        """
        获取实时汇率（基于最新的历史数据）
        """
        try:
            # 获取最近一天的数据
            end_date = datetime.now()
            start_date = end_date - timedelta(days=1)
            
            recent_data = self.get_historical_rates(currency_pair, start_date, end_date)
            
            if not recent_data.empty:
                latest_record = recent_data.iloc[-1]
                return {
                    'symbol': currency_pair,
                    'rate': latest_record['close'],
                    'date': latest_record['date'],
                    'change': latest_record['close'] - latest_record['open']
                }
            else:
                return None
                
        except Exception as e:
            self.logger.error(f"获取实时汇率时出错: {str(e)}")
            return None
